﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SchemaMonitor.json.dict;
using System.Web.Script.Serialization;

namespace SchemaMonitor.json
{
    public class CDict : Dictionary<string, object>
    {
        #region Constructors
        public CDict() : base() { }
        public CDict(int count) : base(count) { }
        public CDict(string json) : this(ToDict(json)) { }
        public CDict(IDictionary<string, object> dict) : base(dict) { }
        public CDict(object dict) : base((IDictionary<string, object>)dict) { }
        #endregion


        #region Instance - Generic
        public Dictionary<string, object> AsDict(string key) { return GetDict(key,   this); }
        public string                     AsStr(string key)  { return GetStr(key,    this); }
        public int                        AsInt(string key)  { return GetInt(key,    this); }
        public bool                      AsBool(string key)  { return GetBool(key,   this); }
        
        public long                      AsLong(string key)  { return GetLng(key,    this); }
        public object                     AsObj(string key)  { return GetObj(key,    this); }
        public object[]                   AsArr(string key)  { return GetObjArr(key, this); }
        public List<string>           AsListStr(string key)  { return GetListStr(key,this); }

        #endregion
        
        #region Instance - Custom ()
        public void FacebookTweaks()
        {

        }
        #endregion

        #region Instance - Custom (Casting)
        public CPaging AsPaging(string key)
        {
            var dict = AsDict(key);
            if (null == dict)
                return null;
            return new CPaging(dict);
        }
        public CCursors AsCursors(string key)
        {
            var dict = AsDict(key);
            if (null == dict)
                return null;
            return new CCursors(dict);
        }
        public CDictError AsError(string key)
        {
            var dict = AsDict(key);
            if (null == dict)
                return null;
            return new CDictError(dict);
        }
        public CToken AsToken(string key)
        {
            var dict = AsDict(key);
            if (null == dict)
                return null;
            return new CToken(dict);
        }
        public CDebugToken AsDebugToken(string key)
        {
            var dict = AsDict(key);
            if (null == dict)
                return null;
            return new CDebugToken(dict);
        }

        //Lists

        public List<CMetaField> AsMetaFields(string key)
        {
            var objs = AsArr(key);
            if (null == objs)
                return null;
            var list = new List<CMetaField>(objs.Length);
            foreach (Dictionary<string, object> i in objs)
                list.Add(new CMetaField(i));
            return list;
        }
        public List<CConnection> AsConnections(string key)
        {
            var dict = AsDict(key);
            if (null == dict)
                return null;
            var list = new List<CConnection>(dict.Count);
            foreach (var i in dict)
                list.Add(new CConnection(i.Key, i.Value.ToString()));
            return list;
        }
        #endregion


        #region Static - JSS
        public static CDict ToDict(string json) { return new CDict(ToDict_(json)); }
        private static Dictionary<string, object> ToDict_(string json)
        {
            return new JavaScriptSerializer()
                .Deserialize<Dictionary<string, object>>(json);
        }
        #endregion


        #region Static - Dict
        //Public
        public static string GetStr(string name, Dictionary<string, object> d)
        {
            return (GetObj(name, d) ?? string.Empty).ToString();
        }
        public static int GetInt(string name, Dictionary<string, object> d)
        {
            int i;
            int.TryParse(GetStr(name, d), out i);
            return i;
        }
        public static long GetLng(string name, Dictionary<string, object> d)
        {
            long i;
            long.TryParse(GetStr(name, d), out i);
            return i;
        }
        public static bool GetBool(string name, Dictionary<string, object> d)
        {
            bool i;
            bool.TryParse(GetStr(name, d), out i);
            return i;
        }
        public static Dictionary<string, object> GetDict(string name, Dictionary<string, object> d)
        {
            var obj = GetObj(name, d);
            return (Dictionary<string, object>)obj;
        }

        public static List<string> GetListStr(string name, Dictionary<string, object> d)
        {
            var obj = GetObjArr(name, d);
            if (null == obj)
                return null;
            var list = new List<object>(obj);
            return list.Cast<string>().ToList();
        }
        public static object[] GetObjArr(string name, Dictionary<string, object> d)
        {
            var obj = GetObj(name, d);
            if (obj == null)
                return new object[] { };    //null

            if (obj is ArrayList)
                return ((ArrayList) obj).ToArray();
            if (obj is object[])
                return (object[])obj;
            return new object[] { obj };
        }

        //private
        private static object GetObj(string name, Dictionary<string, object> d)
        {
            if (null == d)
                return null;
            object obj;
            d.TryGetValue(name, out obj);
            return obj;
        }
        #endregion
    }
}
